package com.woniuxy.ack;

import com.rabbitmq.client.*;
import com.woniuxy.utils.RabbitConnection;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * @Author: linKe
 * @Date: 2022/1/10 16:37
 * @FileName: Consumer
 * @version: 1.0
 * @Description: 消费者--消费确认ACK
 */
@Log4j2
public class ConsumerEmailAck {
    public static void main(String[] args) throws IOException, TimeoutException {
        // 连接通道
        Channel channel = RabbitConnection.getConnection().createChannel();

        channel.queueDeclare("queueEmailTopic", true, false, false, null);

        channel.exchangeDeclare("exchangeTopic", BuiltinExchangeType.TOPIC);

        channel.queueBind("queueEmailTopic", "exchangeTopic", "#.email.#");

        // 第一步：添加限流：指定消费者每次从队列中取几条消息
        channel.basicQos(1);
        /*
        第二步： 修改为手动确认

         */
        channel.basicConsume("queueEmailTopic", false, new DefaultConsumer(channel) {
            /**
             * 处理消息的业务代码
             * @param consumerTag 消息标记，系统会自动分配
             * @param envelope  信封，封装和当前消息相关的消息，后面的手动确认要是用
             * @param properties    发送消息时指定的附加属性
             * @param body          消息体
             */
            @SneakyThrows
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // Thread.sleep(5000);
                log.info("body:" + new String(body));

                if (new String(body).contains("1")) {
                    log.info("Nack");
                    // requeue 重回队列
                    // 手动确认失败，不重回队列
                   /// channel.basicNack(envelope.getDeliveryTag(), false,false);
                    // 确认失败，不重回队列，比上面的方法少中间的参数，一次只能拒绝一个
                    channel.basicReject(envelope.getDeliveryTag(), false);
                } else {
                    // 手动确认处理信息
                /*
                第三步： 服务器收到ACK确认消息，才会真正删除队列中的消息
                    确认一条或多条收到的消息。 从AMQP.Basic.GetOk或AMQP.Basic.Deliver方法提供 deliveryTag，其中包含正在确认的接收消息。
                    参数：
                        deliveryTag – 信封的标记
                            收到的AMQP.Basic.GetOk或AMQP.Basic.Deliver的标签
                        multiple –      是否同时确认
                            true 以确认所有消息，包括提供的交付标签；
                            false 仅确认提供的交付标签。
                 */
                    log.info("Ack");
                    channel.basicAck(envelope.getDeliveryTag(), false);
                    log.info("------------------------------------------------");
                }
            }
        });
    }
}
